<template>
  <el-card shadow="hover" class="mt-20">
    <el-form
      label-width="100px"
      ref="spuFormRef"
      :model="spuFormData"
      :rules="spuFormRules"
    >
      <el-form-item label="SPU名称" prop="spuName">
        <el-input placeholder="SPU名称" v-model="spuFormData.spuName" />
      </el-form-item>
      <el-form-item label="品牌" prop="tmId">
        <el-select v-model="spuFormData.tmId">
          <el-option
            v-for="tm in trademarkList"
            :key="tm.id"
            :label="tm.tmName"
            :value="tm.id"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="SPU描述" prop="description">
        <el-input
          placeholder="SPU名称"
          type="textarea"
          :rows="3"
          v-model="spuFormData.description"
        />
      </el-form-item>
      <el-form-item label="SPU图片" prop="spuImageList">
        <el-upload
          v-model:file-list="spuFormData.spuImageList"
          :action="BASE_URL + '/admin/product/upload'"
          list-type="picture-card"
          :on-preview="handlePictureCardPreview"
          :on-success="handleAvatarSuccess"
          :before-upload="beforeAvatarUpload"
          :limit="10"
          :on-exceed="handleLimitExceeded"
        >
          <el-icon><Plus /></el-icon>
          <template #tip>
            <div class="el-upload__tip">只能上传jpg/png文件，且不超过200kb</div>
          </template>
        </el-upload>
        <el-dialog v-model="dialogVisible">
          <img :src="dialogImageUrl" class="spu-img" />
        </el-dialog>
      </el-form-item>
      <el-form-item label="销售属性" prop="spuSaleAttrList">
        <el-select placeholder="请选择" class="mr-10" v-model="selectSaleAttr">
          <el-option
            v-for="saleAttr in filterBaseSaleAttrList"
            :key="saleAttr.id"
            :label="saleAttr.name"
            :value="`${saleAttr.id}:${saleAttr.name}`"
          />
        </el-select>
        <el-button
          type="primary"
          :icon="Plus"
          :disabled="!selectSaleAttr"
          @click="addSaleAttr"
        >
          添加销售属性
        </el-button>
        <el-table :data="spuFormData.spuSaleAttrList" border class="mt-20">
          <el-table-column
            label="序号"
            type="index"
            align="center"
            width="80"
          />
          <el-table-column label="属性名" prop="saleAttrName" width="200" />
          <el-table-column label="属性值名称列表" prop="xxx">
            <template v-slot="{ row }">
              <el-tag
                type="success"
                v-for="(saleAttrValue, index) in row.spuSaleAttrValueList"
                :key="index"
                class="mr-10"
                closable
                @close="delSpuSaleAttrValue(row, index)"
              >
                {{ saleAttrValue.saleAttrValueName }}
              </el-tag>
              <el-input
                size="small"
                v-if="row.isShowEdit"
                class="spu-inp"
                @blur="switchShow(row)"
                ref="inpRef"
                v-model="saleAttrValueName"
              />
              <el-button
                :icon="Plus"
                size="small"
                v-else
                @click="switchEdit(row)"
              />
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template v-slot="{ $index }">
              <el-button
                type="danger"
                :icon="Delete"
                size="small"
                @click="delSpuSaleAttr($index)"
              />
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="addOrUpdateSpu">保存</el-button>
        <el-button @click="cancel">取消</el-button>
      </el-form-item>
    </el-form>
  </el-card>
</template>

<script lang="ts">
export default {
  name: "AddOrUpdateSpu",
};
</script>

<script lang="ts" setup>
import { getAllTrademarkListApi } from "@/api/product/trademark";
import {
  getBaseSaleAttrListApi,
  addSpuApi,
  updateSpuApi,
  getSpuImageListApi,
  getSpuSaleAttrListApi,
} from "@/api/product/spu";
import type { TrademarkList } from "@/api/product/model/trademarkModel";
import type {
  BaseSaleAttrList,
  AllSpuItem,
  AllSpuSaleAttrList,
  AllSpuSaleAttrItem,
  AllSpuImageItem,
} from "@/api/product/model/spuModel";
import { Plus, Delete } from "@element-plus/icons-vue";
import { onMounted, ref, reactive, computed, nextTick } from "vue";
import { ElMessage } from "element-plus";
import type { UploadProps, UploadUserFile } from "element-plus";
import { beforeAvatarUpload } from "@/utils/tools";
import { useSpuStore } from "@/stores/spu";
import { useCategoryStore } from "@/stores/category";

const trademarkList = ref<TrademarkList>([]);
const baseSaleAttrList = ref<BaseSaleAttrList>([]);

onMounted(async () => {
  trademarkList.value = await getAllTrademarkListApi();
});
onMounted(async () => {
  baseSaleAttrList.value = await getBaseSaleAttrListApi();
});
// 挂载就请求图片数据
onMounted(async () => {
  const id = spuStore.spuItem.id;
  if (!id) return;
  const spuImageList = await getSpuImageListApi(id);
  spuFormData.spuImageList = spuImageList.map((item) => {
    const img = item as AllSpuImageItem;
    return {
      name: img.imgName,
      url: img.imgUrl,
      response: {
        data: img.imgUrl,
      },
    };
  });
});
// 挂载就请求销售属性数据
onMounted(async () => {
  const id = spuStore.spuItem.id;
  if (!id) return;
  spuFormData.spuSaleAttrList = await getSpuSaleAttrListApi(id);
});

// 上传图片
// const fileList = ref([]);

const BASE_URL = import.meta.env.VITE_API_URL;

const dialogImageUrl = ref("");
const dialogVisible = ref(false);

const handlePictureCardPreview: UploadProps["onPreview"] = (uploadFile) => {
  dialogImageUrl.value = uploadFile.url as string;
  dialogVisible.value = true;
};

const handleLimitExceeded = () => {
  ElMessage.error("上传图片最多不能超过10张");
};

// 图片上传成功执行的回调
const handleAvatarSuccess: UploadProps["onSuccess"] = (response) => {
  // 上传成功清空照片的校验结果
  spuFormRef.value.clearValidate(["spuImageList"]);
  // 清空表单校验失败信息
  // trademarkFormRef.value.clearValidate(); // 清空所有表单项的校验信息
};

// 表单校验和收集数据
const spuFormRef = ref();

const spuStore = useSpuStore();

const spuFormData = reactive<AllSpuItem<UploadUserFile>>({
  spuName: spuStore.spuItem.spuName,
  tmId: spuStore.spuItem.tmId,
  description: spuStore.spuItem.description,
  spuImageList: [
    // {
    //   "id": 0,
    //   "imgName": "string",
    //   "imgUrl": "string",
    //   "spuId": 0
    // }
  ],
  spuSaleAttrList: [
    // {
    //   "baseSaleAttrId": 0,
    //   "id": 0,
    //   "saleAttrName": "string",
    //   "spuId": 0,
    //   "spuSaleAttrValueList": [
    //     {
    //       "baseSaleAttrId": 0,
    //       "id": 0,
    //       "isChecked": "string",
    //       "saleAttrName": "string",
    //       "saleAttrValueName": "string",
    //       "spuId": 0
    //     }
    //   ]
    // }
  ],
});

// 自定义校验规则
const spuSaleAttrListValidator = (
  rule: any,
  value: AllSpuSaleAttrList,
  callback: any
) => {
  // 至少添加一个属性
  if (!value.length) {
    callback(new Error("请至少添加一个销售属性"));
    return;
  }
  // 每个销售属性至少添加一个属性值
  if (value.some((item) => !item.spuSaleAttrValueList.length)) {
    callback(new Error("每一个销售属性至少有一个属性值"));
    return;
  }
  // 校验通过
  callback();
};

const spuFormRules = reactive({
  spuName: [{ required: true, message: "请输入SPU名称", trigger: "blur" }],
  tmId: [{ required: true, message: "请选择SPU品牌", trigger: "change" }],
  description: [{ required: true, message: "请输入SPU描述", trigger: "blur" }],
  spuImageList: [{ required: true, message: "请上传SPU图片" }],
  spuSaleAttrList: [
    {
      required: true,
      // message: "请添加SPU销售属性",
      validator: spuSaleAttrListValidator,
    },
  ],
});

// 添加或修改SPU
const categoryStore = useCategoryStore();
const addOrUpdateSpu = async () => {
  try {
    await spuFormRef.value.validate();
    const id = spuStore.spuItem.id;
    const { spuName, tmId, description, spuImageList, spuSaleAttrList } =
      spuFormData;
    const data = {
      category3Id: categoryStore.category3Id,
      spuName,
      tmId,
      description,
      spuImageList: spuImageList.map((item) => {
        const img = item as UploadUserFile;
        return {
          imgName: img.name,
          imgUrl: (img.response as { data: string }).data,
        };
      }),
      spuSaleAttrList,
    };

    if (id) {
      await updateSpuApi({
        ...data,
        id,
      });
    } else {
      await addSpuApi(data);
    }
    ElMessage({
      type: "success",
      message: `${id ? "修改" : "添加"}SPU成功 `,
    });
    cancel();
  } catch (error) {
    //
  }
};

// 销售属性
const selectSaleAttr = ref("");

// 添加销售属性
const addSaleAttr = () => {
  const [id, name] = selectSaleAttr.value.split(":");
  // console.log(id, name);
  spuFormData.spuSaleAttrList.push({
    baseSaleAttrId: +id,
    saleAttrName: name,
    spuSaleAttrValueList: [],
    isShowEdit: false,
  });
};

// 通过计算属性计算出要使用的数据
// 对基础销售属性列表baseSaleAttrList过滤，判断在不在表格中（spuFormData.spuSaleAttrList）
// 在就过滤，不在就保留
const filterBaseSaleAttrList = computed(() => {
  return baseSaleAttrList.value.filter((saleAttr) => {
    return !spuFormData.spuSaleAttrList.some(
      (item) => item.baseSaleAttrId === saleAttr.id
    );
  });
});

// 点击删除销售属性的逻辑
const delSpuSaleAttr = (index: number) => {
  spuFormData.spuSaleAttrList.splice(index, 1);
  // console.log(index);
};
const inpRef = ref();

// 点击切换到编辑模式的逻辑
const switchEdit = async (row: AllSpuSaleAttrItem) => {
  row.isShowEdit = true;
  await nextTick();
  inpRef.value.focus();
};

// 定义输入的销售属性值名称
const saleAttrValueName = ref("");

// 点击切换到显示模式的逻辑
const switchShow = (row: AllSpuSaleAttrItem) => {
  row.isShowEdit = false;
  row.spuSaleAttrValueList.push({
    baseSaleAttrId: row.baseSaleAttrId, // 基础销售属性id
    saleAttrValueName: saleAttrValueName.value, // 销售属性值名称
  });
  // 输完清空输入的内容
  saleAttrValueName.value = "";
};

// 点击删除销售属性值的逻辑
const delSpuSaleAttrValue = (row: AllSpuSaleAttrItem, index: number) => {
  row.spuSaleAttrValueList.splice(index, 1);
};

// 点击取消按钮的逻辑
const emit = defineEmits(["setIsShow"]);
const cancel = () => {
  emit("setIsShow", 1);
};
</script>

<style scoped>
.spu-img {
  width: 100%;
}
.spu-inp {
  width: 200px;
}
</style>
